package com.sjs.boot.dynamic.facade.run;

import com.sjs.boot.dynamic.core.config.method.MethodConfig;
import com.sjs.boot.dynamic.core.config.method.parameter.ParameterInfo;
import com.sjs.boot.dynamic.core.run.MethodContext;
import com.sjs.boot.dynamic.facade.config.AbstractRequestConfig;
import com.sjs.boot.dynamic.facade.config.AbstractResponseConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;

/**
 * @author uto_dev_008
 * @desc
 * @since 2021/11/9 19:50
 */
public abstract class AbstractResponser extends AbstractHandler {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractResponser.class);

    /**
     * 输出model内容到out中
     *
     * @param context method会话
     * @param out
     * @param model
     * @throws ServletException
     * @throws IOException
     */
    abstract protected void output(MethodContext context, OutputStream out, Map<String, Object> model) throws ServletException, IOException;

    abstract protected String getContentType(MethodContext context);

    protected void setContentType(MethodContext context, HttpServletResponse response) {
        response.setContentType(getContentType(context));
    }

    /**
     * 给客户端响应 网页
     *
     * @param context 异步servlet会话
     */
    public void response(MethodContext context)
            throws ServletException, IOException {

        MethodConfig mc = context.getMethodConfig();
        AbstractResponseConfig respConfig = mc.getResponseConfig();
        if (!respConfig.isNeedResponse()) { //不需要框架处理响应
            return;
        }

        HttpServletResponse response = context.getResponse();
        if (response == null) {
            LOG.error("Fail to get response from context, when execute {}", mc.getName());
            return;
        }
        setContentType(context, response);

        Map<String, Object> model = context.getResults();
        AbstractRequestConfig reqCfg = mc.getRequestConfig();
        /**
         * 将需要设置到响应中的内容设置到result中，
         * 在响应json或页面中可以直接使用request中的参数
         * 在参数中增加"response":true配置
         */
        ParameterInfo[] paras = reqCfg.getResponseParameters();
        if (paras != null) {
            for (ParameterInfo pi : paras) {
                model.put(pi.getName(), pi.getValue(context));
            }
        }

        OutputStream out = response.getOutputStream();
        output(context, out, model);
        out.close(); //必须关闭，否则在gzip时，无法返回
    }

    public static final void output(MethodContext context, OutputStream out, byte[] content) {
    }

}
